<?php

namespace app\common\model;

use think\Model;
use think\Db;
use think\Exception;

/**
 * 自定义基础模型类
 * 重写 save() 和 create() 方法，使用直接 SQL 语句而不是 ORM
 */
class CustomBaseModel extends Model
{
    /**
     * 重写 save 方法 - 遍历数组组织 SQL 语句
     * 
     * @param array $data 要保存的数据
     * @param array $where 更新条件（如果为空则插入，否则更新）
     * @param string $sequence 序列名（兼容原方法签名）
     * @return integer|false
     */
    public function save($data = [], $where = [], $sequence = null)
    {
        // 如果 $data 是字符串，按原逻辑处理
        if (is_string($data)) {
            $sequence = $data;
            $data = [];
        }
        
        // 合并当前模型的数据
        if (empty($data)) {
            $data = $this->data;
        } else {
            $data = array_merge($this->data, $data);
        }
        
        if (empty($data)) {
            return false;
        }
        
        try {
            if (empty($where) && !$this->isUpdate) {
                // 插入操作
                return $this->executeInsert($data);
            } else {
                // 更新操作
                if (empty($where) && $this->isUpdate) {
                    // 如果是更新但没有指定条件，使用主键
                    $pk = $this->getPk();
                    if (isset($this->data[$pk])) {
                        $where = [$pk => $this->data[$pk]];
                    }
                }
                return $this->executeUpdate($data, $where);
            }
        } catch (Exception $e) {
            return false;
        }
    }
    
    /**
     * 重写 create 方法 - 直接组织 INSERT SQL
     * 
     * @param array $data 数据数组
     * @param array|true $field 允许字段
     * @return static|false
     */
    public static function create($data = [], $field = null)
    {
        if (empty($data)) {
            return false;
        }
        
        $model = new static();
        
        // 字段过滤
        if (!empty($field)) {
            if ($field === true) {
                // 如果是 true，获取表的所有字段
                $field = $model->getTableFields();
            }
            $data = array_intersect_key($data, array_flip($field));
        }
        
        try {
            $insertId = $model->executeInsert($data);
            if ($insertId) {
                $model->data = $data;
                $model->isUpdate = false;
                
                // 设置主键值
                $pk = $model->getPk();
                if ($pk && !isset($data[$pk])) {
                    $model->data[$pk] = $insertId;
                }
                
                return $model;
            }
        } catch (Exception $e) {
            return false;
        }
        
        return false;
    }
    
    /**
     * 执行插入操作
     * 
     * @param array $data 数据数组
     * @return int|false 返回插入的 ID 或影响行数
     */
    protected function executeInsert($data)
    {
        // 获取表名
        $table = $this->getTable();
        
        // 过滤数据
        $filteredData = $this->filterInsertData($data);
        
        if (empty($filteredData)) {
            return false;
        }
        
        // 构建字段和值
        $fields = [];
        $placeholders = [];
        $bindings = [];
        
        foreach ($filteredData as $field => $value) {
            $fields[] = "`{$field}`";
            
            if ($value === null) {
                $placeholders[] = 'NULL';
            } else {
                $placeholders[] = '?';
                $bindings[] = $value;
            }
        }
        
        // 构建 SQL
        $fieldStr = implode(', ', $fields);
        $valueStr = implode(', ', $placeholders);
        $sql = "INSERT INTO `{$table}` ({$fieldStr}) VALUES ({$valueStr})";
        
        // 执行 SQL
        $result = Db::execute($sql, $bindings);
        
        if ($result) {
            // 返回插入的 ID
            return Db::getLastInsID();
        }
        
        return false;
    }
    
    /**
     * 执行更新操作
     * 
     * @param array $data 数据数组
     * @param array $where 更新条件
     * @return int|false 返回影响的行数
     */
    protected function executeUpdate($data, $where)
    {
        // 获取表名
        $table = $this->getTable();
        
        // 过滤数据
        $filteredData = $this->filterUpdateData($data);
        
        if (empty($filteredData) || empty($where)) {
            return false;
        }
        
        // 构建 SET 子句
        $setParts = [];
        $bindings = [];
        
        foreach ($filteredData as $field => $value) {
            if ($value === null) {
                $setParts[] = "`{$field}` = NULL";
            } else {
                $setParts[] = "`{$field}` = ?";
                $bindings[] = $value;
            }
        }
        
        // 构建 WHERE 子句
        $whereParts = [];
        foreach ($where as $field => $value) {
            if (is_array($value)) {
                // 处理 IN 条件
                $placeholders = str_repeat('?,', count($value) - 1) . '?';
                $whereParts[] = "`{$field}` IN ({$placeholders})";
                $bindings = array_merge($bindings, $value);
            } elseif ($value === null) {
                $whereParts[] = "`{$field}` IS NULL";
            } else {
                $whereParts[] = "`{$field}` = ?";
                $bindings[] = $value;
            }
        }
        
        // 构建完整 SQL
        $setStr = implode(', ', $setParts);
        $whereStr = implode(' AND ', $whereParts);
        $sql = "UPDATE `{$table}` SET {$setStr} WHERE {$whereStr}";
        
        // 执行 SQL
        return Db::execute($sql, $bindings);
    }
    
    /**
     * 过滤插入数据
     * 
     * @param array $data 原始数据
     * @return array 过滤后的数据
     */
    protected function filterInsertData($data)
    {
        $filtered = [];
        
        foreach ($data as $field => $value) {
            // 验证字段名
            if (!$this->isValidFieldName($field)) {
                continue;
            }
            
            // 处理特殊值
            $filtered[$field] = $this->processFieldValue($value);
        }
        
        return $filtered;
    }
    
    /**
     * 过滤更新数据
     * 
     * @param array $data 原始数据
     * @return array 过滤后的数据
     */
    protected function filterUpdateData($data)
    {
        $filtered = [];
        $pk = $this->getPk();
        
        foreach ($data as $field => $value) {
            // 跳过主键字段（更新时不能修改主键）
            if ($field === $pk) {
                continue;
            }
            
            // 验证字段名
            if (!$this->isValidFieldName($field)) {
                continue;
            }
            
            // 处理特殊值
            $filtered[$field] = $this->processFieldValue($value);
        }
        
        return $filtered;
    }
    
    /**
     * 处理字段值
     * 
     * @param mixed $value 原始值
     * @return mixed 处理后的值
     */
    protected function processFieldValue($value)
    {
        // 空字符串转为 null
        if ($value === '') {
            return null;
        }
        
        // 布尔值转为整数
        if (is_bool($value)) {
            return $value ? 1 : 0;
        }
        
        return $value;
    }
    
    /**
     * 验证字段名是否合法
     * 
     * @param string $fieldName 字段名
     * @return bool
     */
    protected function isValidFieldName($fieldName)
    {
        // 只允许字母、数字、下划线，且不能以数字开头
        return preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $fieldName);
    }
    
    /**
     * 批量创建 - 组织批量 INSERT SQL
     * 
     * @param array $dataSet 数据集合
     * @param array|true $field 允许字段
     * @return int|false 返回影响的行数
     */
    public static function createAll($dataSet, $field = null)
    {
        if (empty($dataSet) || !is_array($dataSet)) {
            return false;
        }
        
        $model = new static();
        $table = $model->getTable();
        
        // 字段过滤
        if (!empty($field)) {
            if ($field === true) {
                $field = $model->getTableFields();
            }
            
            foreach ($dataSet as &$data) {
                $data = array_intersect_key($data, array_flip($field));
            }
        }
        
        try {
            return $model->executeBatchInsert($dataSet);
        } catch (Exception $e) {
            return false;
        }
    }
    
    /**
     * 执行批量插入
     * 
     * @param array $dataSet 数据集合
     * @return int|false
     */
    protected function executeBatchInsert($dataSet)
    {
        if (empty($dataSet)) {
            return false;
        }
        
        $table = $this->getTable();
        
        // 获取所有字段（以第一条记录为准）
        $firstRow = reset($dataSet);
        $filteredFirstRow = $this->filterInsertData($firstRow);
        
        if (empty($filteredFirstRow)) {
            return false;
        }
        
        $fields = array_keys($filteredFirstRow);
        $fieldStr = '`' . implode('`, `', $fields) . '`';
        
        // 构建所有行的值
        $allValues = [];
        $bindings = [];
        
        foreach ($dataSet as $data) {
            $filteredData = $this->filterInsertData($data);
            $rowValues = [];
            
            foreach ($fields as $field) {
                $value = isset($filteredData[$field]) ? $filteredData[$field] : null;
                
                if ($value === null) {
                    $rowValues[] = 'NULL';
                } else {
                    $rowValues[] = '?';
                    $bindings[] = $value;
                }
            }
            
            $allValues[] = '(' . implode(', ', $rowValues) . ')';
        }
        
        $valuesStr = implode(', ', $allValues);
        
        // 构建完整的批量 INSERT SQL
        $sql = "INSERT INTO `{$table}` ({$fieldStr}) VALUES {$valuesStr}";
        
        // 执行 SQL
        return Db::execute($sql, $bindings);
    }
}
